#include "CycleLooper.h"

#include <iostream>
#include <future>

CycleLooper::CycleLooper()
{
    this->worker = std::thread([this](){ this->handle(); });
    running = true;
}

CycleLooper::~CycleLooper()
{
    if (running)
    {
        quit();
    }
}

void CycleLooper::enqueue(const Message& msg)
{
    // unique_lock 会锁定锁，并在析构时释放锁
    std::unique_lock<std::mutex> lock(guard);
    // wait 如果进入等待会释放锁
    signal.wait(lock, [this]() { return !this->isFull(); });
    // wait 结束后重新锁定锁，获得锁，

    this->queue[this->tail] = msg;
    this->tail = (this->tail + 1) % MAX_MESSAGE_COUNT;
    ++count;
    {
        std::lock_guard<std::mutex> lockCoutGuard(guardCout);
        std::cout << "enqueue tail message: " << msg.msg << " count:" << count << " ,Tail: " << this->tail
                  << " ,  Full:" << this->isFull() << std::endl;
    }

    signal.notify_one();
}

void CycleLooper::enqueueHead(const Message& msg)
{
    // unique_lock 会锁定锁，并在析构时释放锁
    std::unique_lock<std::mutex> lock(guard);
    // wait 如果进入等待会释放锁
    signal.wait(lock, [this]() { return !this->isFull(); });
    // wait 结束后重新锁定锁，获得锁，

    this->head = (this->head - 1 + MAX_MESSAGE_COUNT) % MAX_MESSAGE_COUNT;
    this->queue[this->head] = msg;
    ++count;

    {
        std::lock_guard<std::mutex> lockCoutGuard(guardCout);
        std::cout << "enqueue head message: " << msg.msg << " count:" << count << " ,Tail: " << this->head
                  << " ,  Full:" << this->isFull() << std::endl;
    }

    signal.notify_one();
}

void CycleLooper::handleSync(Message msg, bool immediately)
{
    std::promise<void> promise;
    msg.fun = [&promise](){ promise.set_value(); };

    if (immediately)
    {
        this->enqueueHead(msg);
    }
    else
    {
        this->enqueue(msg);
    }

    // 先自旋一段时间，减少线程切换
    std::atomic_int32_t n = 0;
    while (n++ < 100000) {}

    // 如果没用执行完则进入等待
    {
        std::lock_guard<std::mutex> lockCoutGuard(guardCout);
        std::cout << "handleSync Lock Wait! " << std::endl;
    }
    auto future = promise.get_future();
    future.get();

    {
        std::lock_guard<std::mutex> lockCoutGuard(guardCout);
        std::cout << "handleSync Finish: msg="<< msg.msg <<" immediately=" << immediately  << std::endl;
    }
}

void CycleLooper::dequeue(Message& msg)
{
    // unique_lock 会锁定锁，并在析构时释放锁
    std::unique_lock<std::mutex> lock(guard);
    // wait 如果进入等待会释放锁
    signal.wait(lock, [this]() { return !this->isEmpty(); });
    // wait 结束后重新锁定锁，获得锁，

    msg = std::move(queue[this->head]);
    this->head = (this->head + 1) % MAX_MESSAGE_COUNT;
    --count;
    {
        std::lock_guard<std::mutex> lockCoutGuard(guardCout);
        std::cout << "dequeue, msg="<< msg.msg << " count:" << count << " ,Head: " << this->head << " ,  Empty:" << this->isEmpty()
                  << std::endl;
    }
    signal.notify_one();
}

void CycleLooper::handle()
{
    using namespace std;
    Message msg;

    while (true)
    {
        this->dequeue(msg);
        if (msg.quit)
        {
            break ;
        }
        {
            std::lock_guard<std::mutex> lockCoutGuard(guardCout);
            cout << "Handling Message:" << msg.msg << endl;
        }
        this_thread::sleep_for(std::chrono::milliseconds(4000));
        {
            std::lock_guard<std::mutex> lockCoutGuard(guardCout);
            cout << "Finish Message:" << msg.msg << endl;
        }

        if (msg.fun)
        {
            msg.fun();
        }
    }

    cout << "Handle finish" << endl;

}

void CycleLooper::quit()
{
    this->enqueue({ "", true });

    worker.join();
    running = false;
    std::cout << "Looper exit!\n";

}